package finn.movingheadtracker.gui;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;

import java.awt.Color;
import java.awt.Dimension;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JList;
import javax.swing.JButton;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.JPanel;

import java.awt.Component;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import finn.movingheadtracker.DmxMerger;
import finn.movingheadtracker.MergedUniverse;
import finn.movingheadtracker.MergedUniverse.ChannelMergeMode;
import finn.movingheadtracker.Universe;

import javax.swing.JRadioButton;
import javax.swing.JComboBox;

import java.awt.Label;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;

public class SettingsframeDmxMerger extends JDialog{
	//The showed MergedUniverse
	static int MUid = 0;
	
	
	JLabel lblspecChannel;
	JLabel lblspecValue;
	JLabel lblMergingType;
	JPanel pnlChannelInputs;
	
	static int viewType = 0; //0 for dmx value, 1 for input selection, 2 for merging type

	
	static JComboBox<String> cmbbViewInputSelection = new JComboBox<String>();
	

	private JList<ChannelOverviewField> lstChannelOverview;
	
	JList<String> lstMergedUniverses = new JList<String>();
	public SettingsframeDmxMerger(JFrame SuperFrame){
		super(SuperFrame,"Einstellungen: DmxMerger");
		
		JLabel lblNewLabel = new JLabel("Merged Universes");
		
		JScrollPane scrollPane = new JScrollPane();
		
		JButton btnAddMergedUniverse = new JButton("Hinzuf\u00FCgen");
		
		JButton btnDelMergedUniverse = new JButton("Entfernen");
		
		JLabel lblInput = new JLabel("Input");
		
		JScrollPane scrollPane_1 = new JScrollPane();
		
		JLabel lblOutput = new JLabel("Output");
		
		JButton btnAddInput = new JButton("Hinzuf\u00FCgen");
		
		JButton btn = new JButton("Entfernen");
		
		JScrollPane scrollPane_2 = new JScrollPane();
		
		JButton btnHinzufgen_2 = new JButton("Hinzuf\u00FCgen");
		
		JButton btnEntfernen_2 = new JButton("Entfernen");
		
		JSeparator separator = new JSeparator();
		separator.setOrientation(SwingConstants.VERTICAL);
		
		JLabel lblbersicht = new JLabel("\u00DCbersicht");
		
		JScrollPane scrollPane_3 = new JScrollPane();
		
		JLabel lblAnsichtWhlen = new JLabel("Ansicht w\u00E4hlen");
		
		JSeparator separator_1 = new JSeparator();
		
		JRadioButton rdbtnInputSelection = new JRadioButton("Input Selection");
		rdbtnInputSelection.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				viewType = 1;
				lstChannelOverview.updateUI();
			}
		});
		JRadioButton rdbtnMergingType = new JRadioButton("Merging Type");
		rdbtnMergingType.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				viewType = 2;
				lstChannelOverview.updateUI();
			}
		});
		JRadioButton rdbtnViewDmxValue = new JRadioButton("Dmx Value");
		rdbtnViewDmxValue.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				viewType = 0;
				lstChannelOverview.updateUI();
			}
		});
		rdbtnViewDmxValue.setSelected(true);
		
		ButtonGroup ViewSelection = new ButtonGroup();
		ViewSelection.add(rdbtnInputSelection);
		ViewSelection.add(rdbtnMergingType);
		ViewSelection.add(rdbtnViewDmxValue);
		
		
		JLabel lblEditMergeduniverse = new JLabel("Edit MergedUniverse");
		final ButtonGroup SetBy = new ButtonGroup();
		
		
		JPanel lblspecMergingMode = new JPanel();
		
		GroupLayout groupLayout = new GroupLayout(getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING, false)
							.addComponent(scrollPane_1, GroupLayout.PREFERRED_SIZE, 203, GroupLayout.PREFERRED_SIZE)
							.addComponent(scrollPane, Alignment.LEADING, GroupLayout.PREFERRED_SIZE, 203, GroupLayout.PREFERRED_SIZE)
							.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
								.addComponent(lblOutput)
								.addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 108, GroupLayout.PREFERRED_SIZE)
								.addGroup(groupLayout.createSequentialGroup()
									.addComponent(btnAddMergedUniverse)
									.addGap(21)
									.addComponent(btnDelMergedUniverse))
								.addComponent(lblInput)
								.addGroup(groupLayout.createSequentialGroup()
									.addComponent(btnAddInput)
									.addGap(21)
									.addComponent(btn)))
							.addGroup(groupLayout.createSequentialGroup()
								.addComponent(btnHinzufgen_2)
								.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
								.addComponent(btnEntfernen_2)))
						.addComponent(scrollPane_2, GroupLayout.PREFERRED_SIZE, 203, GroupLayout.PREFERRED_SIZE)
						.addComponent(separator_1, GroupLayout.PREFERRED_SIZE, 203, GroupLayout.PREFERRED_SIZE)
						.addComponent(lblAnsichtWhlen)
						.addComponent(rdbtnViewDmxValue)
						.addGroup(groupLayout.createSequentialGroup()
							.addComponent(rdbtnInputSelection)
							.addPreferredGap(ComponentPlacement.UNRELATED)
							.addComponent(cmbbViewInputSelection, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE))
						.addComponent(rdbtnMergingType))
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(separator, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addComponent(lblbersicht)
							.addGap(434))
						.addGroup(groupLayout.createSequentialGroup()
							.addComponent(lblEditMergeduniverse)
							.addContainerGap(370, Short.MAX_VALUE))
						.addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
							.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
								.addComponent(lblspecMergingMode, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 475, Short.MAX_VALUE)
								.addComponent(scrollPane_3, GroupLayout.DEFAULT_SIZE, 475, Short.MAX_VALUE))
							.addContainerGap())))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
								.addComponent(separator, GroupLayout.DEFAULT_SIZE, 541, Short.MAX_VALUE)
								.addGroup(groupLayout.createSequentialGroup()
									.addComponent(lblbersicht)
									.addPreferredGap(ComponentPlacement.RELATED)
									.addComponent(scrollPane_3, GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE)
									.addGap(6)
									.addComponent(lblEditMergeduniverse)
									.addPreferredGap(ComponentPlacement.RELATED)
									.addComponent(lblspecMergingMode, GroupLayout.PREFERRED_SIZE, 130, GroupLayout.PREFERRED_SIZE)
									.addGap(15)))
							.addGap(6))
						.addGroup(groupLayout.createSequentialGroup()
							.addComponent(lblNewLabel)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 88, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
								.addComponent(btnAddMergedUniverse)
								.addComponent(btnDelMergedUniverse))
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(lblInput)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(scrollPane_1, GroupLayout.PREFERRED_SIZE, 63, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
								.addComponent(btnAddInput)
								.addComponent(btn))
							.addPreferredGap(ComponentPlacement.UNRELATED)
							.addComponent(lblOutput)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(scrollPane_2, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
								.addComponent(btnEntfernen_2)
								.addComponent(btnHinzufgen_2))
							.addGap(15)
							.addComponent(separator_1, GroupLayout.PREFERRED_SIZE, 7, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(lblAnsichtWhlen)
							.addPreferredGap(ComponentPlacement.UNRELATED)
							.addComponent(rdbtnViewDmxValue)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
								.addComponent(rdbtnInputSelection)
								.addComponent(cmbbViewInputSelection, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(rdbtnMergingType)
							.addContainerGap())))
		);
		
		//Setting up the list in the middle of the Window
		lstChannelOverview = new JList<ChannelOverviewField>();
		lstChannelOverview.setVisibleRowCount(-1);
		lstChannelOverview.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		lstChannelOverview.setCellRenderer(new CellRenderer());
		ChannelOverviewField[] lstdata = new ChannelOverviewField[512];
		for(int i=0;i<512;i++){
			lstdata[i] = new ChannelOverviewField(i);
		}
		lstChannelOverview.setListData(lstdata);
		lstChannelOverview.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent arg0) {
				if(lstChannelOverview.getSelectedValuesList().size()==1){
					viewChannel(lstChannelOverview.getSelectedValue().id);
				}
			}
		});
		scrollPane_3.setViewportView(lstChannelOverview);
		
		//Setting up the List in the upper left corner With the MergedUniverses
		scrollPane.setViewportView(lstMergedUniverses);
		lstMergedUniverses.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent arg0) {
				MUid = Integer.parseInt(lstMergedUniverses.getSelectedValue());
				UpdateAll();
			}
		});
		scrollPane.setViewportView(lstMergedUniverses);
		String[] lst = new String[DmxMerger.mergedUniverses.size()];
		for(int i = 0; i< DmxMerger.mergedUniverses.size();i++){
			lst[i] = DmxMerger.mergedUniverses.get(i).toString();
		}
		lstMergedUniverses.setListData(lst);
		
		//Setting up the specific Channel View Field
		GridBagLayout gbl_lblspecMergingMode = new GridBagLayout();
		gbl_lblspecMergingMode.columnWidths = new int[]{107, 56, 0};
		gbl_lblspecMergingMode.rowHeights = new int[] {0, 0, 0};
		gbl_lblspecMergingMode.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
		gbl_lblspecMergingMode.rowWeights = new double[]{1.0, 1.0, 1.0};
		lblspecMergingMode.setLayout(gbl_lblspecMergingMode);
		
		lblspecChannel = new JLabel("Channel #0");
		GridBagConstraints gbc_lblspecChannel = new GridBagConstraints();
		gbc_lblspecChannel.insets = new Insets(0, 0, 5, 5);
		gbc_lblspecChannel.gridx = 0;
		gbc_lblspecChannel.gridy = 0;
		lblspecMergingMode.add(lblspecChannel, gbc_lblspecChannel);
		
		JScrollPane scrollPane_4 = new JScrollPane();
		GridBagConstraints gbc_scrollPane_4 = new GridBagConstraints();
		gbc_scrollPane_4.gridheight = 3;
		gbc_scrollPane_4.insets = new Insets(0, 0, 5, 0);
		gbc_scrollPane_4.fill = GridBagConstraints.BOTH;
		gbc_scrollPane_4.gridx = 1;
		gbc_scrollPane_4.gridy = 0;
		lblspecMergingMode.add(scrollPane_4, gbc_scrollPane_4);
		
		pnlChannelInputs = new JPanel();
		scrollPane_4.setViewportView(pnlChannelInputs);
		pnlChannelInputs.setLayout(new BoxLayout(pnlChannelInputs, BoxLayout.Y_AXIS));
		
		lblspecValue = new JLabel("Value 102");
		GridBagConstraints gbc_lblspecValue = new GridBagConstraints();
		gbc_lblspecValue.insets = new Insets(0, 0, 5, 5);
		gbc_lblspecValue.gridx = 0;
		gbc_lblspecValue.gridy = 1;
		lblspecMergingMode.add(lblspecValue, gbc_lblspecValue);
		
		lblMergingType = new JLabel("LTP");
		GridBagConstraints gbc_lblMergingType = new GridBagConstraints();
		gbc_lblMergingType.insets = new Insets(0, 0, 0, 5);
		gbc_lblMergingType.gridx = 0;
		gbc_lblMergingType.gridy = 2;
		lblspecMergingMode.add(lblMergingType, gbc_lblMergingType);
		
		//Setting up the list with all Universes Output
		JList<Universe> listOutputs = new JList<Universe>();
		scrollPane_2.setViewportView(listOutputs);
		
		//Setting up the list with all Universes Input
		JList<Universe> listInputs = new JList<Universe>();
		scrollPane_1.setViewportView(listInputs);
		
		getContentPane().setLayout(groupLayout);
		
		this.setSize(new Dimension(762, 607));
		setVisible(true);
	} 
	/**
	 * Update the Channel View Field
	 * @param channel the Channel to display
	 */
	public void viewChannel(int channel){
		if(MUid==0){
			this.lblMergingType.setText("HTP");
			this.lblMergingType.setBackground(Color.GREEN);
			this.lblMergingType.setOpaque(true);
			this.lblspecValue.setText("Value 0");
			this.lblspecChannel.setText("Channel #"+String.valueOf(channel));
			return;
		}
		MergedUniverse mu = DmxMerger.getMergedUniverse(MUid);
		if(mu.getMergingType(channel)==ChannelMergeMode.LTP){
			this.lblMergingType.setText("LTP");
			this.lblMergingType.setBackground(Color.BLUE);
		}
		else{
			this.lblMergingType.setText("HTP");
			this.lblMergingType.setBackground(Color.GREEN);
		}
		this.lblMergingType.setOpaque(true);
		this.lblspecValue.setText("Value " + String.valueOf(DmxMerger.getMergedUniverse(MUid).getValue(channel)));
		this.lblspecChannel.setText("Channel #"+String.valueOf(channel));
		this.setActiveInputs(DmxMerger.getMergedUniverse(MUid).getCMMInput(channel));
	}
	/**
	 * Updates the ChannelView fields inputs
	 * @param ids All Ids available in this MergedUniverse
	 */
	public void setAllInputs(int[] ids){
		this.pnlChannelInputs.removeAll();
		for(int id:ids){
			JCheckBox jck = new JCheckBox();
			jck.setText(String.valueOf(id) + ": " + DmxMerger.getUniverse(id).name);
			this.pnlChannelInputs.add(jck);
		}
		this.pnlChannelInputs.updateUI();
		
	}
	
	/**
	 * Set all selected Inputs in the Channel View Field
	 * @param ids Array with all Ids
	 */
	public void setActiveInputs(int[] ids){
		Component[] cmps = pnlChannelInputs.getComponents();
		for(Component cmp: cmps){
			if(cmp instanceof JCheckBox){
				String[] idStrings = ((JCheckBox)cmp).getText().split(":",2);
				for(int id:ids){
					if(id==Integer.valueOf(idStrings[0])){
						((JCheckBox)cmp).setSelected(true);
						break ;
					}
					else{
						((JCheckBox)cmp).setSelected(false);
					}
				}
			}
		}
	}
	
	/**
	 * Get all selected ids in the Channel View Field
	 * @return List with selected Integers
	 */
	public Integer[] getActiveInputs(){
		Component[] cmps = pnlChannelInputs.getComponents();
		List<Integer> returnlst = new ArrayList<Integer>();
		for(Component cmp: cmps){
			if(cmp instanceof JCheckBox){
				if(((JCheckBox)cmp).isSelected()){
					String[] split = ((JCheckBox)cmp).getText().split(":");
					returnlst.add(Integer.parseInt(split[0]));
				}
			}
		}
		return (Integer[])returnlst.toArray();
	}
	
	public void UpdateMergedUniverses(){
		int selected_index = lstMergedUniverses.getSelectedIndex();
		String[] lst = new String[DmxMerger.mergedUniverses.size()];
		for(int i = 0; i< DmxMerger.mergedUniverses.size();i++){
			lst[i] = DmxMerger.mergedUniverses.get(i).toString();
		}
		lstMergedUniverses.setListData(lst);
		if(lstMergedUniverses.getModel().getSize()!=0){
			while(lstMergedUniverses.getModel().getSize()>=selected_index){
				selected_index--;
			}
			lstMergedUniverses.setSelectedIndex(selected_index);
		}
		this.lstMergedUniverses.updateUI();
	}
	/**
	 * Updates all Lists and the ChannelView
	 */
	public void UpdateAll(){
		this.lstChannelOverview.updateUI();
		this.setAllInputs(DmxMerger.getMergedUniverse(MUid).getInput());
	}
	
	public class ChannelOverviewField{
		int id;
		
		public ChannelOverviewField(int i){
			this.id = i;
		}
		@Override
		public String toString(){
			return "CH #" + String.valueOf(id+1);
		}
	}
	
	public class CellRenderer implements ListCellRenderer<ChannelOverviewField>{

		@Override
		public Component getListCellRendererComponent(
				JList<? extends ChannelOverviewField> arg0,
				ChannelOverviewField arg1, int index, boolean selected,
				boolean arg4) {
			LineBorder eBorder = new LineBorder(new Color(255,255,255), 2);
			LineBorder linebd = new LineBorder(new Color(255,255,255),2);
			JLabel ret = new JLabel(arg1.toString());
			if(SettingsframeDmxMerger.MUid==0){
				if(selected==true){
					linebd = new LineBorder(new Color(0,0,0),2);
				}
				ret.setBorder(BorderFactory.createCompoundBorder(eBorder, linebd));
				return ret;
			}
			if(selected==true){
				linebd = new LineBorder(new Color(0,0,0),2);
			}
			if(SettingsframeDmxMerger.viewType==0){
				int vl = (int)DmxMerger.getMergedUniverse(SettingsframeDmxMerger.MUid).getValue(arg1.id);
				ret.setBackground(new Color(255,255-vl,255-vl));
			}
			else if(SettingsframeDmxMerger.viewType==2){
				if(DmxMerger.getMergedUniverse(MUid).getMergingType(arg1.id)==ChannelMergeMode.LTP){
					ret.setBackground(Color.BLUE);
				}
				else{
					ret.setBackground(Color.GREEN);
				}
			}
			ret.setBorder(BorderFactory.createCompoundBorder(eBorder, linebd));
			ret.setOpaque(true);
			return ret;
		}
	}
}